package kiwi.assist.dev.guieditor.mediator {
	import fl.core.UIComponent;

	import ghostcat.display.other.GContextMenu;
	import ghostcat.operation.DelayOper;
	import ghostcat.operation.FunctionOper;
	import ghostcat.operation.Queue;

	import kiwi.assist.dev.guieditor.event.GUIEditorEvent;
	import kiwi.assist.dev.guieditor.event.GUIOperateEvent;
	import kiwi.assist.dev.guieditor.model.ContainerConfig;
	import kiwi.assist.dev.guieditor.model.GUIEditorConfig;
	import kiwi.assist.dev.guieditor.model.UiConfig;
	import kiwi.assist.dev.util.SkinComponentAdapter;

	import org.robotlegs.mvcs.Mediator;

	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.filters.GlowFilter;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.ui.Mouse;
	import flash.ui.MouseCursor;

	/**
	 * 可编辑的ui
	 * @author zhangming.luo
	 */
	public class EditableUiMediator extends Mediator {
		public static const GLOW_BLUE : Array = [new GlowFilter(0x0000ff, 0.8, 6, 6, 2, 1)];
		private var ui : UIComponent;
		private var queue : Queue = new Queue();
		private var editable : Boolean;
		private var draging : Boolean;
		private var startDragPos : Point;
		private var startPos : Point;
		private var resizing : Boolean;
		private var startSize : Point;
		[Inject]
		public var config : GUIEditorConfig;
		private var uiConfig : UiConfig;

		override public function onRegister() : void {
			super.onRegister();
			ui = UIComponent(viewComponent);
			uiConfig = config.getUiConfigByDos(ui);
			ui.parent.addEventListener(MouseEvent.ROLL_OVER, onRollOver, false, int.MAX_VALUE, true);
			ui.parent.addEventListener(MouseEvent.ROLL_OUT, onRollOut, false, int.MAX_VALUE, true);
			ui.parent.addEventListener(MouseEvent.CLICK, onClick, false, int.MAX_VALUE, true);
			ui.parent.addEventListener(MouseEvent.DOUBLE_CLICK, onDblClick, false, int.MAX_VALUE, true);
			ui.parent.addEventListener(MouseEvent.MOUSE_DOWN, handleMouse, false, int.MAX_VALUE, true);
			ui.parent.addEventListener(MouseEvent.MOUSE_UP, handleMouse, false, int.MAX_VALUE, true);
			ui.parent.addEventListener(MouseEvent.MOUSE_MOVE, handleMouseMove, false, int.MAX_VALUE, true);
			ui.addEventListener(Event.RESIZE, onResize, false, 0, true);
			ui.addEventListener(Event.CHANGE, onChange, false, 0, true);
			addContextListener(GUIOperateEvent.START_EDIT, handleStartEdit, GUIOperateEvent, false, 0, true);
			bindMenu();
		}

		private function onChange(event : Event) : void {
			dispatch(new GUIOperateEvent(GUIOperateEvent.CHANGE_VALUE, ui));
		}

		private function bindMenu() : void {
			var menu : GContextMenu = new GContextMenu();
			menu.addMenu("移除", removeUi);
			menu.addMenu("替换", replaceUi);
			menu.addSeparator();
			menu.addMenu("向上", function() : void {
				moveUi(1);
			});
			menu.addMenu("向下", function() : void {
				moveUi(-1);
			});
			menu.addMenu("最上", function() : void {
				moveUi(int.MAX_VALUE);
			});
			menu.addMenu("最下", function() : void {
				moveUi(int.MIN_VALUE);
			});
			menu.addSeparator();
			menu.addMenu("复制到下方", function() : void {
				cloneUi(ui, ui.x, ui.y + ui.height);
			});
			menu.addMenu("复制到右方", function() : void {
				cloneUi(ui, ui.x + ui.width, ui.y);
			});
			if (ui is SkinComponentAdapter) {
				menu.addSeparator();
				menu.addMenu(SkinComponentAdapter(ui).skin.name);
			}
			menu.parse(ui);
		}

		private function replaceUi() : void {
			if (ui is SkinComponentAdapter) {
				dispatch(new GUIEditorEvent(GUIEditorEvent.SHOW_BACKGROUND_SELECT_DIALOG, ui));
			} else {
				dispatch(new GUIEditorEvent(GUIEditorEvent.SHOW_UI_SELECT_DIALOG, ui));
			}
		}

		private function cloneUi(ui : UIComponent, x : Number, y : Number) : void {
			dispatch(new GUIOperateEvent(GUIOperateEvent.CLONE_UI, ui, {x:x, y:y}));
		}

		private function moveUi(step : int) : void {
			dispatch(new GUIOperateEvent(GUIOperateEvent.LAYER_MOVE, ui, step));
		}

		private function removeUi() : void {
			if (ui is SkinComponentAdapter) {
				dispatch(new GUIOperateEvent(GUIOperateEvent.BACKGROUND_REMOVE, ui));
			} else {
				dispatch(new GUIOperateEvent(GUIOperateEvent.UI_REMOVE, ui));
			}
		}

		private function handleStartEdit(event : GUIOperateEvent) : void {
			if (event.targetUi != ui) {
				exitEditMode();
			}
		}

		private function handleMouseMove(event : MouseEvent) : void {
			var rect : Rectangle = new Rectangle(0, 0, ui.width, ui.height);
			if (rect.containsPoint(new Point(ui.mouseX, ui.mouseY))) {
				// 没事
				Mouse.cursor = MouseCursor.AUTO;
			} else {
				Mouse.cursor = "HVDrag";
			}
		}

		private function getMouseState(event : MouseEvent) : String {
			var rect : Rectangle = new Rectangle(0, 0, ui.width, ui.height);
			if (rect.containsPoint(new Point(event.localX, event.localY))) {
				return "over_ui";
			}
			return "over_editor";
		}

		private function handleMouse(event : MouseEvent) : void {
			if (event.type == MouseEvent.MOUSE_DOWN) {
				// 开始准备拖拽了
				switch(getMouseState(event)) {
					case "over_ui":
						queue.commitChild(new DelayOper(100));
						queue.commitChild(new FunctionOper(startDrag));
						break;
					case "over_editor":
						startResize();
				}
			} else if (event.type == MouseEvent.MOUSE_UP) {
				stopDrag();
			}
			event.stopImmediatePropagation();
		}

		private function startResize() : void {
			enterEditMode();
			draging = true;
			resizing = true;
			startDragPos = new Point(ui.stage.mouseX, ui.stage.mouseY);
			startSize = new Point(ui.width, ui.height);
			ui.stage.addEventListener(MouseEvent.MOUSE_MOVE, onStageMouseMove);
			ui.stage.addEventListener(MouseEvent.MOUSE_UP, onStageMouseUp);
			draw();
		}

		private function startDrag() : void {
			enterEditMode();
			if (config.getUiConfigByDos(ui) is ContainerConfig) {
				return;
			}
			draging = true;
			resizing = false;
			Mouse.cursor = MouseCursor.HAND;
			startDragPos = new Point(ui.stage.mouseX, ui.stage.mouseY);
			startPos = new Point(ui.x, ui.y);
			ui.stage.addEventListener(MouseEvent.MOUSE_MOVE, onStageMouseMove);
			ui.stage.addEventListener(MouseEvent.MOUSE_UP, onStageMouseUp);
			dispatch(new GUIOperateEvent(GUIOperateEvent.START_DRAG, ui));
			draw();
		}

		private function onStageMouseUp(event : MouseEvent) : void {
			stopDrag();
		}

		private function onStageMouseMove(event : MouseEvent) : void {
			if (resizing) {
				var _newWidth : int = startSize.x + ui.stage.mouseX - startDragPos.x;
				var _newHeight : int = startSize.y + ui.stage.mouseY - startDragPos.y;
				if (event.ctrlKey) {
					_newHeight = _newWidth / startSize.x * startSize.y;
				}
				if (!uiConfig.isFixedWidth) {
					ui.width = _newWidth;
				}
				if (!uiConfig.isFixedHeight) {
					ui.height = _newHeight;
				}
				ui.dispatchEvent(new Event(Event.CHANGE));
			} else {
				if (!uiConfig.isFixedPosition) {
					if (event.shiftKey) {
						// 单一方向
						if (ui.stage.mouseX - startDragPos.x > ui.stage.mouseY - startDragPos.y) {
							// 偏X方向
							ui.x = startPos.x + ui.stage.mouseX - startDragPos.x;
						} else {
							// 偏Y方向
							ui.y = startPos.y + ui.stage.mouseY - startDragPos.y;
						}
					} else {
						ui.x = startPos.x + ui.stage.mouseX - startDragPos.x;
						ui.y = startPos.y + ui.stage.mouseY - startDragPos.y;
					}
				}
			}
			event.updateAfterEvent();
		}

		private function stopDrag() : void {
			queue.halt();
			Mouse.cursor = MouseCursor.AUTO;
			draging = false;
			if (ui.stage) {
				ui.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onStageMouseMove);
				ui.stage.removeEventListener(MouseEvent.MOUSE_UP, onStageMouseUp);
			}
			ui.dispatchEvent(new Event(Event.CHANGE));
		}

		private function enterEditMode() : void {
			// 增加一个比较明显的编辑标记
			editable = true;
			dispatch(new GUIOperateEvent(GUIOperateEvent.START_EDIT, ui));
			draw();
		}

		private function exitEditMode() : void {
			editable = false;
			draw();
		}

		private function onResize(event : Event) : void {
			draw();
		}

		private function draw() : void {
			ui.graphics.clear();
			if (editable) {
				// 画四格格子
				ui.graphics.beginFill(resizing ? 0x0000ff : 0xffffff);
				ui.graphics.drawRect(-5, -5, 5, 5);
				ui.graphics.drawRect(ui.width, -5, 5, 5);
				ui.graphics.drawRect(ui.width, ui.height, 5, 5);
				ui.graphics.drawRect(-5, ui.height, 5, 5);
			} else {
			}
		}

		private function onDblClick(event : MouseEvent) : void {
			event.stopImmediatePropagation();
		}

		private function onClick(event : MouseEvent) : void {
			event.stopImmediatePropagation();
			ui.stage.focus = ui.parent;
			enterEditMode();
		}

		private function onRollOut(event : MouseEvent) : void {
			if (draging) {
				onStageMouseMove(event);
			} else {
				stopDrag();
			}
			event.stopImmediatePropagation();
		}

		private function onRollOver(event : MouseEvent) : void {
			event.stopImmediatePropagation();
		}
	}
}
